package com.mars.manager.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.mars.base.common.exception.AppException;
import com.mars.base.service.BaseService;
import com.mars.component.redis.JedisClient;
import com.mars.manager.constrants.RedisNamespace;
import com.mars.manager.entity.Menu;
import com.mars.manager.exception.MenuBizException;
import com.mars.manager.mapper.MenuMapper;
import com.mars.manager.vo.MenuVo;

@Service
public class MenuServiceImpl extends BaseService<Menu, Long> implements MenuService {

	@Autowired
	private MenuMapper mapper;
	
	@Autowired
	private JedisClient jedisClient ;
	
	@Override
	public int insertSelective(Menu entity) throws AppException {
		this.cleanCache();
		if(null != entity && entity.getSelected() == 1) {
			this.uploadMenuSelect();
		}
		return super.insertSelective(entity);
	}
	
	@Override
	public int updateSelective(Menu entity) throws AppException {
		this.cleanCache();
		if(null != entity && entity.getSelected() == 1) {
			this.uploadMenuSelect();
		}
		return super.updateSelective(entity);
	}

	@Override
	public int deleteByIds(List<Long> idList) throws AppException {
		for (Long id : idList) {
			recursiveDelete(id);
		}
		this.cleanCache();
		return 0 ;
	}
	
	private void recursiveDelete(Long id) {
		List<MenuVo> loadChildrenNode = this.loadChildrenNode(id) ;
		
		if(null != loadChildrenNode) {
			for (MenuVo menu : loadChildrenNode) {
				recursiveDelete(menu.getId());
			}
		}
		super.delete(id) ;
	}
	
	@Override
	public List<Menu> selectList(Menu entity) throws AppException {
		String menuList = this.jedisClient.get(RedisNamespace.MENU_LIST) ;
		if(null != menuList) {
			return JSON.parseArray(menuList, Menu.class) ;
		} else {
			List<Menu> list = super.selectList(entity);
			this.jedisClient.set(RedisNamespace.MENU_LIST, JSON.toJSONString(list));
			return list;
		}
	}
	
	@Override
	public List<MenuVo> loadRootNode() throws MenuBizException {
		String menuList = this.jedisClient.get(RedisNamespace.MENU_TREE_ROOT) ;
		if(null != menuList) {
			return JSON.parseArray(menuList, MenuVo.class) ;
		} else {
			List<MenuVo> list = this.mapper.loadRootNode();
			this.jedisClient.set(RedisNamespace.MENU_TREE_ROOT, JSON.toJSONString(list));
			return list;
		}
	}

	@Override
	public List<MenuVo> loadChildrenNode(Long pid) throws MenuBizException {
		List<MenuVo> list = new ArrayList<MenuVo>();
		
		List<MenuVo> childs = this.mapper.loadChildrenNode(pid);
		for (MenuVo menu : childs) {
			list.add(recursive(menu));
		}
		
		return list;
	}

	@Override
	public List<MenuVo> tree() throws MenuBizException {
		List<MenuVo> list = new ArrayList<MenuVo>();
		
		List<MenuVo> root = this.loadRootNode();
		for (MenuVo menu : root) {
			list.add(recursive(menu));
		}
		return list;
	}

	@Override
	public List<MenuVo> treegrid() throws MenuBizException {
		List<MenuVo> list = new ArrayList<MenuVo>();
		
		List<MenuVo> root = this.loadRootNode();
		for (MenuVo menu : root) {
			list.add(recursive(menu));
		}
		return list;
	}


	private MenuVo recursive(MenuVo menu) {
		menu.setIconCls("icon-standard-application-view-list");
		String menuJosn = this.jedisClient.getHash(RedisNamespace.MENU_TREE_CHILDREN, "ID_" + menu.getId()) ;
		if(null != menuJosn) {
			return JSON.parseObject(menuJosn, MenuVo.class) ;
		} else {
			List<MenuVo> childs = this.mapper.loadChildrenNode(menu.getId()) ;
			if (null != childs && childs.size() > 0) {
				List<MenuVo> children = new ArrayList<MenuVo>();
				for (MenuVo m : childs) {
					m.setIconCls("icon-standard-application-view-list");
					children.add(recursive(m));
				}
				menu.setChildren(children);
			}
			this.jedisClient.setHash(RedisNamespace.MENU_TREE_CHILDREN, "ID_" + menu.getId(), JSON.toJSONString(menu));
			return menu;
		}
		
	}

	@Override
	public Long cleanCache() {
		return this.jedisClient.delKeys(RedisNamespace.MENU_LIST, RedisNamespace.MENU_TREE, RedisNamespace.MENU_TREE_CHILDREN, RedisNamespace.MENU_TREE_ROOT, RedisNamespace.MENU_TREEGRID) ;
	}

	@Override
	public void uploadMenuSelect() {
		this.mapper.uploadMenuSelect();
	}
}
